﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using DailyDiet.Models;
using DailyDiet.Services.Constant;
using DailyDiet.util;

namespace DailyDiet.Services.Impl
{
    /*菜品图片存储策略
     *
     *每个图片单独存放，文件名为 DietPicture+id.txt
     * 每个图片存放后，在偏好存贮中标记为以存储，key为 DietPicture+id
     */
    /// <summary>
    /// 菜品图片服务
    /// </summary>
    public class DietPictureService : IDietPictureService {
        private IPreferenceStorage _preference;

        private string _imagePath =
            Environment.GetFolderPath(Environment.SpecialFolder
                .LocalApplicationData);

        /// <summary>
        /// 获取一个菜品的图片
        /// </summary>
        /// <param name="dietId">菜品ID</param>
        /// <returns></returns>
        public async Task<byte[]> GetOneDietPictureAsync(Diet diet) {
            byte[] imageBytes;
            //从本地读取
            if (IsStorageInLocalFile(diet.Id)) {
                return await GetPictureFromLocalFileAsync(diet.Id);
            }
            //从web获取
            imageBytes = await GetPictureFromWebAsync(diet.PictureURL);
            //本地存储
            if (imageBytes != null && imageBytes.Length > 0) {
                await StoragePictureInLocalFileAsync(diet.Id, imageBytes);
                _preference.Set(DietPictureConstant.BasePreferenceKey+diet.Id,DietPictureConstant.InLocalFile);
            }

            return imageBytes;
        }

        /// <summary>
        /// 获取多个菜品的图片
        /// </summary>
        /// <param name="diets">菜品集合</param>
        /// <returns>一个id为key，图片字节为value的字典</returns>
        public async Task<Dictionary<int, byte[]>> GetDietPicturesAsync(List<Diet> diets) {
            Dictionary<int, byte[]> idBytesMap = new Dictionary<int, byte[]>();
            foreach (var diet in diets) {
                idBytesMap[diet.Id] = await GetOneDietPictureAsync(diet);
            }

            return idBytesMap;
        }

        /// <summary>
        /// 判断该改菜品图片是否保存在本地 default = -1 
        /// </summary>
        /// <param name="dietId"></param>
        /// <returns></returns>
        public bool IsStorageInLocalFile(int dietId) =>
            _preference.Get(DietPictureConstant.BasePreferenceKey + dietId,
                DietPictureConstant.DefaultStorageState) ==
            DietPictureConstant.InLocalFile;
        

        /// <summary>
        /// 从网络获取图片
        /// </summary>
        /// <param name="url">图片url地址</param>
        /// <returns></returns>
        public async Task<byte[]> GetPictureFromWebAsync(string url) {
            byte[] imageBytes = null;
            using (var httpClient = new HttpClient()) {
                HttpResponseMessage response;
                try {
                    response = await httpClient.GetAsync(url);
                } catch (Exception e) {
                    Console.WriteLine(e);
                    return imageBytes;
                }
                imageBytes = await response.Content.ReadAsByteArrayAsync();
            }
            return imageBytes;
        }

        /// <summary>
        /// 从本地文件获取图片
        /// </summary>
        /// <param name="dietId"></param>
        /// <returns></returns>
        public async Task<byte[]> GetPictureFromLocalFileAsync(int dietId) {
            string filePath = Path.Combine(_imagePath,
                DietPictureConstant.BaseFileName + dietId);

            if (!File.Exists(filePath)) {
                //标记为不存在
                _preference.Set(DietPictureConstant.BasePreferenceKey + dietId,
                    DietPictureConstant.DefaultStorageState);
                throw new FileNotExistButPreferenceMarkItInLocalFileException();
            }

            byte[] imageBytes = null;

            var imageMemoryStream = new MemoryStream();
            using (var imageFileStream =
                new FileStream(filePath, FileMode.Open))
            {
                await imageFileStream.CopyToAsync(imageMemoryStream);
            }

            imageBytes = imageMemoryStream.ToArray();
            return imageBytes;
        }

        /// <summary>
        /// 将图片字节存储到本地
        /// </summary>
        /// <param name="dietId">图片对应的DietID</param>
        /// <param name="imageBytes">图片字节</param>
        /// <returns></returns>
        public async Task StoragePictureInLocalFileAsync(int dietId, byte[] imageBytes) {
            string filePath = Path.Combine(_imagePath,
                DietPictureConstant.BaseFileName + dietId);

            using (var imageFileStream =
                new FileStream(filePath, FileMode.OpenOrCreate))
            {
                await imageFileStream.WriteAsync(imageBytes, 0, imageBytes.Length);
                imageFileStream.Flush();
            }
        }

        public DietPictureService(IPreferenceStorage preference) {
            _preference = preference;
        }

    }
}
